/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package pos.Driving.Path.Segment;

import pos.Driving.Path.*;
import pos.Driving.Path.Segment.Segment;
import pos.utils.*;
import com.sun.j3d.utils.geometry.*;
import javax.media.j3d.*;
import javax.vecmath.*;
/**
 * 区段3D模型生成工厂
 * @author 郑昊
 */

public class SectionFactory {
    //private static Group Model10MLift=ObjectFactory.createObject("Model.Rail.10MLift",true);
    //private static Group Model10MGround=ObjectFactory.createObject("Model.Rail.10MGround",true);
    //private static Group Model10MLiftInner, Model10MLiftOutter;
    private static Group Model10MDualRail
            =ObjectFactory.createObject("Model.Rail.Rail10MDual",true);
    private static Group Model50MDaozha
            =ObjectFactory.createObject("Model.Rail.Base50MDaozha",true);
    private static Group Model50MDaozhaR
            =ObjectFactory.createObject("Model.Rail.Base50MDaozhaR",true);
    private static Group Model50MDaozhaStation
            =ObjectFactory.createObject("Model.Rail.Base50MDaozhaStation",true);
    private static Group Model50MLiftBridge
            =ObjectFactory.createObject("Model.Rail.Base50MSingleLift",true);
    private static Group Model50MSingleTunnel
            =ObjectFactory.createObject("Model.Rail.Base50MSingleTunnel",true);
    private static Segment CurrentSegment;
    private static int PathID;
    
    public static Group MakeSection(Segment seg,int pathID, double s, double t){
        CurrentSegment=seg;
        PathID=pathID;
        Group res=new Group();
        res.addChild(MakeRail(s,t));
        res.addChild(MakeBase(s,t));
        return res;
    }
    private static Group MakeRail(double s, double t){
        Group res=new Group();
        PosPoint p=new PosPoint();
        p.path_ID=PathID;
        double length=t-s;
        int segments;
        if (((int)length)% 50 !=0) 
            segments=(int)length/50;
        else
            segments=(int)length/50-1;
        for (int i=0; i<=segments; i++){
            p.d=s+i*50;
            p=CurrentSegment.getPosPoint(p);
            try{
                res.addChild(applyTransform(s+i*50d,t,Model10MDualRail,true,5));
            }catch(Exception e){
                System.err.println("S:"+(s)+" T:"+t+" @Path"+ PathID);
            }
        }
        return res;
    }
    
    private static Group MakeBase(double s, double t){
        Group res=new Group();
        PosPoint p=new PosPoint();
        p.path_ID=PathID;
        double length=t-s;
        int segments;
        if (((int)length)% 50 !=0) 
            segments=(int)length/50;
        else
            segments=(int)length/50-1;
        for (int i=0; i<=segments; i++){
            p.d=s+i*50d;
            p=CurrentSegment.getPosPoint(p);
            switch (p.PATH_TYPE){
                case PosPoint.PATH_SINGLE_LIFT:{
                    res.addChild(applyTransform(s+i*50d,t,Model50MLiftBridge,true));
                    //res.addChild(applyTransform(s+i*50d,t,Model50MDaozha,true));
                    break;
                }
                case PosPoint.PATH_STATION:{
                    res.addChild(applyTransform(s+i*50d,t,Model50MDaozhaStation,true));
                    //res.addChild(applyTransform(s+i*50d,t,Model50MDaozha,true));
                    break;
                }
                case PosPoint.PATH_SINGLE_TUNNEL:{
                    //System.out.println("D:"+(s+i*50d)+" z:"+p.pos.z);
                    res.addChild(applyTransform(s+i*50d,t,Model50MSingleTunnel,true));
                    break;
                }
                case PosPoint.PATH_GROUND:{
                    res.addChild(applyTransform(s+i*50d,t,Model50MDaozha,true));
                    //res.addChild(applyTransform(s+i*50d,t,Model50MDaozha,true));
                    break;
                }
                case PosPoint.PATH_GROUND_R:{
                    res.addChild(applyTransform(s+i*50d,t,Model50MDaozhaR,true));
                    //res.addChild(applyTransform(s+i*50d,t,Model50MDaozha,true));
                    break;
                }
            }
            
        }
        return res;
    }
    
    private static Group applyTransform(double start,double end, Group g, 
            boolean liftFix, double lengthIncrease){
        Group res;
        res=(Group)g.cloneTree();
        Transform3D transH=new Transform3D(),transV=new Transform3D(), transT=new Transform3D();
        PosPoint p=new PosPoint();
        p.path_ID=PathID;
        for (int i=0; i<res.numChildren(); i++){
                Node n=res.getChild(i);
                if (n instanceof Shape3D){
                    Shape3D shape=(Shape3D)n;
                    for (int j=0; j<shape.numGeometries();j++ ){
                        Geometry geo=shape.getGeometry(j);
                        if (geo instanceof GeometryArray){
                            GeometryArray geoArray=(GeometryArray) geo;
                            Point3f [] tempCoord;//=new Point3f();
                            GeometryInfo geoInfo=new GeometryInfo(geoArray);

                            tempCoord = geoInfo.getCoordinates();
                            for(int v=0; v<tempCoord.length; v++){
                                if(start+tempCoord[v].x*lengthIncrease<=end){
                                    p.d=start+tempCoord[v].x*lengthIncrease;
                                }else{
                                    p.d=end;
                                    
                                }
                                p=CurrentSegment.getPosPoint(p);
                                if (!liftFix || tempCoord[v].y>-5)
                                    transH.rotX(p.AngH);
                                   
                                transV.rotY(p.AngV);
                                transT.set(new Vector3d(
                                        p.pos.x,p.pos.y,p.pos.z));
                                
                                transT.mul(transV);
                                transT.mul(transH);
                                tempCoord[v].x=0;
                                transT.transform(tempCoord[v]);
                            }
                            geoInfo.setCoordinates(tempCoord);
                            ((Shape3D)res.getChild(i)).setGeometry(geoInfo.getGeometryArray(true,false,true));
                        }
                    }
                }
            }
        return res;
        
    }
    private static Group applyTransform(double start,double end, Group g, boolean liftFix){
        return applyTransform(start,end,g,liftFix,1d);
    }
    private static Group applyTransform(double start,double end, Group g){
        return applyTransform(start,end,g,false,1d);
        
    }

}
